package com.hippy.erya.common.utils;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.security.*;
import java.util.*;
import java.util.Map.Entry;

/**
 * 统一签名验证签名
 */
@Slf4j
public class SecurityCommonUtil {

    /** 双方通信统一采用utf-8编码, 各种内部逻辑中的字节向字符转换也统一以utf-8形式 */
    public static final String CHARSET = "UTF-8";

    /** 对称加密具体算法实现 */
    public static final String AES_ALGORITHM = "AES/CFB/PKCS5Padding";

    /** 非对称加密具体算法实现 */
    public static final String RSA_ALGORITHM = "RSA/ECB/PKCS1Padding";

    /** 签名算法的实现 */
    public static final String SIGN_ALGORITHM = "SHA256withRSA";

    public static final String RETURN_FAIL="FAIL";//失败

    public static final String RETURN_SUCCESS="SUCCESS";//成功

    private static final char[] hexArray = "0123456789ABCDEF".toCharArray();

    private static final String encryptionAlgorithm = "SHA-1";
    private static String sIvParameter_Pinfo = "0123456789abcdef";
    private static final byte[] DECODE_TABLE = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
            0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,
            0, 0, 0, 0 };

    // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ "
    private static final byte[] ENCODE_TABLE = new byte[] { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
            114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47 };

    static {
        // create encode table
        // ENCODE_TABLE = new byte[64];
        int index = 0;
        for (char c = 'A'; c <= 'Z'; c++)
            ENCODE_TABLE[index++] = (byte) c;
        for (char c = 'a'; c <= 'z'; c++)
            ENCODE_TABLE[index++] = (byte) c;
        for (char c = '0'; c <= '9'; c++)
            ENCODE_TABLE[index++] = (byte) c;
        ENCODE_TABLE[index++] = (byte) '+';
        ENCODE_TABLE[index++] = (byte) '/';

        // create decode table
        for (int i = 0; i < 64; i++)
            DECODE_TABLE[(int) ENCODE_TABLE[i]] = (byte) i;
    }



    /**
     * 带有数据加密逻辑的发送请求示例（使用密码）
     *
     * @param token
     * @param aesKey
     */
    public static Map<String,Object> encodeMesByPassword(String token, String aesKey,String signStr,String icode) throws BadPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, UnsupportedEncodingException, NoSuchPaddingException, InvalidKeyException {

        Map<String,Object> result = new HashMap<>();
        Map<String,Object> mapObj = new HashMap<>();
//        parseJSON2Map(mapObj,jsonStr,null);
        //map排序转签名字段
//        String signStr = map2strWithAsc(mapObj);
        Map<String,String> parms = new HashMap<String,String>();
        String aesKeyWithBase64 = genRandomAesSecretKey().replaceAll("\\=","");//密码戳
        parms.put("terminalType", icode);
        parms.put("token", token);
        parms.put("timestamp", aesKeyWithBase64);
        String signature = encyMd5(signStr,parms);
        //将参数加入请求字段，并base64编码转化
        String minwen = "signStr="+signStr +"&timestamp="+aesKeyWithBase64+"&signature="+signature;
        System.out.println("明文="+minwen);
        String aesStr = Base64.encodeBase64String(minwen.getBytes("UTF-8"));
        System.out.println("aesStr="+aesStr);
        String data =  encryptPinfo(aesStr, aesKey);
        result.put("minwen",minwen);
        result.put("data",data);

        return result;
    }

    public static Map<String,Object> encodeMesByPassword1(String token, String aesKey,String jsonStr,String icode) throws BadPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, UnsupportedEncodingException, NoSuchPaddingException, InvalidKeyException {

        Map<String,Object> result = new HashMap<>();
        Map<String,Object> mapObj = new HashMap<>();
        //parseJSON2Map(mapObj,jsonStr,null);
        //map排序转签名字段
       //String signStr = map2strWithAsc(mapObj);
        Map<String,String> parms = new HashMap<String,String>();
        byte[] aesKeyWithBase64 = genRandomAesSecretKey(aesKey);//密码戳
        parms.put("terminalType", icode);
        parms.put("token", token);
        parms.put("timestamp", Base64.encodeBase64String(aesKeyWithBase64).replaceAll("\\=",""));
        String signature = encyMd5(jsonStr,parms);
        //将参数加入请求字段，并base64编码转化
        String minwen = jsonStr +"&timestamp="+Base64.encodeBase64String(aesKeyWithBase64).replaceAll("\\=","")+"&signature="+signature;
        String aesStr = Base64.encodeBase64String(minwen.getBytes("UTF-8"));
        System.out.println("明文="+minwen);
        System.out.println("aesStr="+aesStr);
        String data =  encryptPinfo(aesStr, aesKeyWithBase64);
        System.out.println("data="+data);
        result.put("minwen",minwen);
        result.put("data",data);

        return result;
    }

    /**
     * 带有数据加密逻辑的发送返回示例（使用密码）
     *
     * @param token
     * @param aesKey
     */
    public static Map<String, Object> decodeMesByPassword(String token, String aesKey,String data)
             {
        //转换成明文
        String aesStr = decryptPinfo(data,aesKey);
        String minwen =  new String(Base64.decodeBase64(aesStr));
        Map<String,Object>  returnMap = new HashMap<String,Object>();
        returnMap.put("code", "0000");
        returnMap.put("message","接收报文成功！");
        returnMap.put("signStr",minwen);
        returnMap.put("minwen",minwen);
//        returnMap.put("classMap",classMap);

        return returnMap;

    }

    /**
     * Aes 256
     * @param content
     * @param password
     * @return
     */
    public static String encrypt256(String content, String password) {
        try {
            //"AES"：请求的密钥算法的标准名称
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            //256：密钥生成参数；securerandom：密钥生成器的随机源
            SecureRandom securerandom = new SecureRandom(tohash256Deal(password));
            kgen.init(256, securerandom);
            //生成秘密（对称）密钥
            SecretKey secretKey = kgen.generateKey();
            //返回基本编码格式的密钥
            byte[] enCodeFormat = secretKey.getEncoded();
            //根据给定的字节数组构造一个密钥。enCodeFormat：密钥内容；"AES"：与给定的密钥内容相关联的密钥算法的名称
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            //将提供程序添加到下一个可用位置
             Security.addProvider(new BouncyCastleProvider());
            //创建一个实现指定转换的 Cipher对象，该转换由指定的提供程序提供。
            //"AES/ECB/PKCS7Padding"：转换的名称；"BC"：提供程序的名称
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //偏移量
            IvParameterSpec iv = new IvParameterSpec(sIvParameter_Pinfo.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, key,iv);
            byte[] byteContent = content.getBytes("utf-8");
            byte[] cryptograph = cipher.doFinal(byteContent);
            return new String(encode(cryptograph));
        } catch (Exception e) {
            log.error("加密异常=",e);
        }
        return null;
    }
    /**
     * 将指定字符串做hash算法处理
     * @param datastr	需要被处理的字符串
     * @return
     */
    private static byte[] tohash256Deal(String datastr) {
        try {
            /**
             * MessageDigest : 该类是个抽象类，此类为应用程序提供信息摘要算法的功能，如 MD5 或 SHA 算法。信息摘要是安全的单向哈希函数，它接收任意大小的数据，输出固定长度的哈希值。
             * getInstance(String algorithm) ： 生成实现指定摘要算法的 MessageDigest 对象。
             * algorithm : 所请求算法的名称。
             * 该对象通过使用 update 方法处理数据。任何时候都可以调用 reset 方法重置摘要。一旦所有需要更新的数据都已经被更新了，应该调用 digest 方法之一完成哈希计算。
             */
            MessageDigest digester=MessageDigest.getInstance("SHA-256");
            /**
             * update(byte[] input) : 使用指定的字节数组更新摘要。
             */
            digester.update(datastr.getBytes());
            /**
             * digest() : 通过执行诸如填充之类的最终操作完成哈希计算。调用此方法后摘要被重置。
             */
            byte[] hex=digester.digest();
            /**
             * hex : 存放哈希值结果的字节数组。
             */
            return hex;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /*
     * 验证密文
     */
    public static boolean decyMd5(String jsonStr,String signature,Map<String,String> parms){

        String terminalType = parms.get("terminalType");
        String token = parms.get("token");
        String timestamp = parms.get("timestamp");

        String digest = digest(jsonStr, "MD5");
        boolean isValid = isValid(signature, terminalType, digest, timestamp,token);
        return isValid;

    }

    public  static final  boolean isValid(String signature, String appid, String lol,
                                          String millis,String token) {
        String calculatedSignature = generateSignature(appid, token, lol,
                millis);
        log.info("calculated signature: 【" + calculatedSignature + "】");
        if (StringUtils.equals(calculatedSignature, signature)) {
            return true;
        } else {
            return false;
        }
    }

    /*
     * AES密码解密
     */
    public static String decryptPinfo(String sSrc,String key)  {
        try {
            byte[] raw = key.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(sIvParameter_Pinfo.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = decode(sSrc.getBytes());
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "utf-8");
            return originalString;
        } catch (Exception ex) {
            return null;
        }
    }

    /*
     * AES密码加密
     */
    public static String encryptPinfo(String sSrc,String key) {
        try{
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] raw = key.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            IvParameterSpec iv = new IvParameterSpec(sIvParameter_Pinfo.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));

            return new String(encode(encrypted));
        } catch (Exception ex) {
            log.error("加密异常=",ex);
            return null;
        }
    }

    public static String encryptPinfo(String sSrc,byte[] key) {
        try{
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//            byte[] raw = key.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
            IvParameterSpec iv = new IvParameterSpec(sIvParameter_Pinfo.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));

            return new String(encode(encrypted));
        } catch (Exception ex) {
            return null;
        }
    }

    public static byte[] encode(byte[] data) {
        if (data == null)
            return null;

        int fullGroups = data.length / 3;
        int resultBytes = fullGroups * 4;
        if (data.length % 3 != 0)
            resultBytes += 4;

        byte[] result = new byte[resultBytes];
        int resultIndex = 0;
        int dataIndex = 0;
        int temp = 0;
        for (int i = 0; i < fullGroups; i++) {
            temp = (data[dataIndex++] & 0xff) << 16 | (data[dataIndex++] & 0xff) << 8 | data[dataIndex++] & 0xff;

            result[resultIndex++] = ENCODE_TABLE[(temp >> 18) & 0x3f];
            result[resultIndex++] = ENCODE_TABLE[(temp >> 12) & 0x3f];
            result[resultIndex++] = ENCODE_TABLE[(temp >> 6) & 0x3f];
            result[resultIndex++] = ENCODE_TABLE[temp & 0x3f];
        }
        temp = 0;
        while (dataIndex < data.length) {
            temp <<= 8;
            temp |= data[dataIndex++] & 0xff;
        }
        switch (data.length % 3) {
            case 1:
                temp <<= 8;
                temp <<= 8;
                result[resultIndex++] = ENCODE_TABLE[(temp >> 18) & 0x3f];
                result[resultIndex++] = ENCODE_TABLE[(temp >> 12) & 0x3f];
                result[resultIndex++] = 0x3D;
                result[resultIndex++] = 0x3D;
                break;
            case 2:
                temp <<= 8;
                result[resultIndex++] = ENCODE_TABLE[(temp >> 18) & 0x3f];
                result[resultIndex++] = ENCODE_TABLE[(temp >> 12) & 0x3f];
                result[resultIndex++] = ENCODE_TABLE[(temp >> 6) & 0x3f];
                result[resultIndex++] = 0x3D;
                break;
            default:
                break;
        }

        return result;
    }

    public static byte[] decode(byte[] base64Data) {
        if (base64Data == null)
            return null;
        if (base64Data.length == 0)
            return new byte[0];
        if (base64Data.length % 4 != 0)
            throw new IllegalArgumentException("数据不完整，长度为： " + base64Data.length);

        byte[] result = null;
        int groupCount = base64Data.length / 4;

        int lastData = base64Data.length;
        while (base64Data[lastData - 1] == 0x3D) {
            if (--lastData == 0)
                return new byte[0];
        }
        result = new byte[lastData - groupCount];

        int temp = 0;
        int resultIndex = 0;
        int dataIndex = 0;
        for (; dataIndex + 4 < base64Data.length;) {
            temp = DECODE_TABLE[base64Data[dataIndex++]];
            temp = (temp << 6) + (DECODE_TABLE[base64Data[dataIndex++]] & 0xff);
            temp = (temp << 6) + (DECODE_TABLE[base64Data[dataIndex++]] & 0xff);
            temp = (temp << 6) + (DECODE_TABLE[base64Data[dataIndex++]] & 0xff);

            result[resultIndex++] = (byte) ((temp >> 16) & 0xff);
            result[resultIndex++] = (byte) ((temp >> 8) & 0xff);
            result[resultIndex++] = (byte) (temp & 0xff);
        }

        temp = 0;
        int j = 0;
        for (; dataIndex < base64Data.length; dataIndex++, j++)
            temp = (temp << 6) + (DECODE_TABLE[base64Data[dataIndex]] & 0xff);
        for (; j < 4; j++)
            temp <<= 6;

        result[resultIndex++] = (byte) ((temp >> 16) & 0xff);
        if (base64Data[dataIndex - 2] != '=')
            result[resultIndex++] = (byte) ((temp >> 8) & 0xff);
        if (base64Data[dataIndex - 1] != '=')
            result[resultIndex++] = (byte) (temp & 0xff);

        return result;
    }

    /*
     * MD5加密
     */
    public static String encyMd5(String jsonStr,Map<String,String> parms){

        String terminalType = parms.get("terminalType");
        String token = parms.get("token");
        String timestamp = parms.get("timestamp");

        String digest = digest(jsonStr, "MD5");
        System.out.println(digest);
        String signature = generateSignature(terminalType, token, digest,timestamp);
        return signature;

    }

    public  static final  String digest(String strSrc, String encName) {
        MessageDigest md = null;
        String strDes = null;

        try {
            byte[] bt = strSrc.getBytes("utf-8");
            if (encName == null || encName.equals("")) {
                encName = "MD5";
            }
            md = MessageDigest.getInstance(encName);
            md.update(bt);
            strDes = bytesToHexString(md.digest()); // to HexString
        } catch (NoSuchAlgorithmException e) {
            log.error("Invalid algorithm: " + encName);
            return null;
        }catch (UnsupportedEncodingException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return strDes;
    }

    /**
     * 根据appid、token以及时间戳来生成签名
     *
     * @param appid
     * @param token
     * @param lol
     * @param millis
     * @return
     */
    public  static final  String generateSignature(String appid, String token, String lol,
                                                   String millis) {
        String timestamp = String.valueOf(millis);
        String signature = null;
        if (StringUtils.isNotBlank(token) && StringUtils.isNotBlank(timestamp)
                && StringUtils.isNotBlank(appid)) {
            List<String> srcList = new ArrayList<String>();
            srcList.add(timestamp);
            srcList.add(appid);
            srcList.add(token);
            srcList.add(lol);
            // 按照字典序逆序拼接三个参数
            Collections.sort(srcList);
            Collections.reverse(srcList);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < srcList.size(); i++) {
                sb.append(srcList.get(i));
            }
            signature = digest(sb.toString(), encryptionAlgorithm);
            srcList.clear();
            srcList = null;
        }
        return signature;
    }

    public static final String bytesToHexString(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }


    /**
     * 获取随机的对称加密的密钥，返回的密钥经过了base64编码
     */
    private static String genRandomAesSecretKey() throws NoSuchAlgorithmException, UnsupportedEncodingException,
            IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchPaddingException {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(128);
        SecretKey secretKey = keyGen.generateKey();
        return Base64.encodeBase64String(secretKey.getEncoded());
    }

    private static byte[] genRandomAesSecretKey(String key) throws NoSuchAlgorithmException, UnsupportedEncodingException,
            IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchPaddingException {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");

        SecureRandom sr = new SecureRandom(key.getBytes());
        keyGen.init(256,sr);
        SecretKey secretKey = keyGen.generateKey();
        return secretKey.getEncoded();
    }
    /**
     * 获取随机的对称加密的IV，返回的IV经过了base64编码
     */
    private static String genRandomIV() {
        SecureRandom r = new SecureRandom();
        byte[] iv = new byte[16];
        r.nextBytes(iv);
        return Base64.encodeBase64String(iv);
    }

    private static String genRandom() {
        SecureRandom r = new SecureRandom();
        byte[] iv = new byte[16];
        r.nextBytes(iv);
        return String.valueOf(iv);
    }

    /**
     * 对称加密数据
     *
     * @param keyWithBase64
     *            base64编码后的密钥
     * @param ivWithBase64
     *            base64编码后的IV
     * @param plainText
     *            待加密的明文
     * @return 经过对称加密，且base64编码后的数据
     */
    private static String encryptAES(String keyWithBase64, String ivWithBase64, String plainText)
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException,
            BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {

        SecretKeySpec key = new SecretKeySpec(Base64.decodeBase64(keyWithBase64), "AES");
        IvParameterSpec iv = new IvParameterSpec(Base64.decodeBase64(ivWithBase64));

        Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);

        return Base64.encodeBase64String(cipher.doFinal(plainText.getBytes(CHARSET)));
    }

    /**
     * 对称解密数据
     *
     * @param keyWithBase64
     *            base64编码后的密钥
     * @param ivWithBase64
     *            base64编码后的IV
     * @param cipherText
     *            待解密的密文
     * @return 解密出的明文
     */
    private static String decryptAES(String keyWithBase64, String ivWithBase64, String cipherText)
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException,
            BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
        SecretKeySpec key = new SecretKeySpec(Base64.decodeBase64(keyWithBase64), "AES");
        IvParameterSpec iv = new IvParameterSpec(Base64.decodeBase64(ivWithBase64));

        Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        return new String(cipher.doFinal(Base64.decodeBase64(cipherText)), CHARSET);
    }

    /**
     * 非对称加密，根据公/私钥和明文产生密文
     *
     * @param key
     *            加密用的公钥或私钥
     * @param plainText
     *            待加密的明文
     * @return 经过非对称加密，且base64编码后的数据
     */
    public static String encryptRSA(Key key, String plainText)
            throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException,
            BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return Base64.encodeBase64String(cipher.doFinal(plainText.getBytes(CHARSET)));
    }

    /**
     * 非对称解密，根据公/私钥和密文解出明文
     *
     * @param key
     *            解密用的公钥或私钥
     * @param cipherText
     *            待解密的密文
     * @return 解密出的明文
     */
    private static String decryptRSA(Key key, String cipherText) throws NoSuchPaddingException,
            NoSuchAlgorithmException, InvalidKeyException, DecoderException, BadPaddingException,
            IllegalBlockSizeException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return new String(cipher.doFinal(Base64.decodeBase64(cipherText)), CHARSET);
    }

    /**
     * 对输入的map，以key升序的形式排序，并以key=value&key=value形式拼接在一起
     *
     * @param paramMap
     * @return 拼接完成的大字符串
     */
    private static String map2strWithAsc(Map<String, Object> paramMap) {
        Map<String, Object> params = new TreeMap<String, Object>(paramMap);
        StringBuffer strBu = new StringBuffer();
        for (Entry<String, Object> entry : params.entrySet()) {
            strBu.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
//            if(entry.getValue()!=null) {
//                strBu.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
//            }
        }
        int iLen = strBu.length();
        if(iLen>0){
            return strBu.substring(0, strBu.length()-1);
        }
        else{
            return null;
        }

    }

    /**
     * 对输入的map，以key升序的形式排序，并以json形式拼接在一起，暂不使用
     *
     * @param paramMap
     * @return 拼接完成的大字符串
     */
    private static String map2jsonWithAsc(Map<String, String> paramMap) {
        Map<String, String> params = new TreeMap<String, String>(paramMap);
        //map排序
        Map<String, String> sortMap = new TreeMap<String, String>(new Comparator<String>() {
            public int compare(String obj1, String obj2) {
                return obj1.compareTo(obj2);//升序排序
            }
        });
        sortMap.putAll(paramMap);

        //map转json
        return  JSON.toJSONString(sortMap);

    }

    private static Map<String, String> str2MapWithAsc(String minwen, String token, String terminalType) {
        Map<String, String> params = new TreeMap<String, String>();
        params.put("token", token);
        params.put("terminalType", terminalType);
        String[] str = minwen.split("\\&");
        for (String s : str) {
            if (StringUtils.isBlank(s)) {
                continue;
            }
            int index = s.indexOf("=");
            String key = s.substring(0, index);
            String value = s.substring(index + 1);
            if (StringUtils.isNotBlank(key)) {
                params.put(key, value);
            }
        }
        return params;
    }


    /**
     * 生成签名
     *
     * @param key
     *            生成签名用的密钥
     * @param content
     *            生成sha256时使用的数据
     * @return 根据content生成的sha256值，经过加密、base64编码后的内容
     */
    private static String sign(PrivateKey key, String content) throws NoSuchAlgorithmException, InvalidKeyException,
            DecoderException, SignatureException, UnsupportedEncodingException {
        Signature signature = Signature.getInstance(SIGN_ALGORITHM);
        signature.initSign(key);
        signature.update(content.getBytes(CHARSET));
        return Base64.encodeBase64String(signature.sign());
    }

    /**
     * 验证签名
     *
     * @param key
     *            验证签名使用的公钥，由签名生成方发放
     * @param content
     *            生成签名的原始数据
     * @param sign
     *            签名生成方发送过来的签名(经过密钥加密、base64编码后的值)
     * @return
     */
    private static boolean verify(PublicKey key, String content, String sign) throws NoSuchAlgorithmException,
            InvalidKeyException, DecoderException, SignatureException, UnsupportedEncodingException {
        Signature signature = Signature.getInstance(SIGN_ALGORITHM);
        signature.initVerify(key);
        signature.update(content.getBytes(CHARSET));
        return signature.verify(Base64.decodeBase64(sign));
    }
    /**
     * list根据指定字段排序
     *
     * @param reqList
     *            需排序list
     * @param sortFileld
     *            排序字段
     * @return
     */
    public static Map<String,Object> sortList(List reqList, String sortFileld,String headStr) throws ClassNotFoundException,
            IllegalAccessException {

        Collections.sort(reqList, new Comparator<Object>(){
            @Override
            public int compare(Object o1, Object o2) {
                Class oa1 = o1.getClass();
                Class oa2 = o2.getClass();
                try {
                    Field field1 = oa1.getDeclaredField(sortFileld);
                    Field field2 = oa2.getDeclaredField(sortFileld);
                    field1.setAccessible(true);
                    field2.setAccessible(true);
                    String sortStr1 = (String)field1.get(o1);
                    String sortStr2 = (String)field2.get(o2);
                    if(sortStr1.compareTo(sortStr2)>0){
                        return 1;
                    }else if(sortStr1.compareTo(sortStr2)<0){
                        return -1;
                    }
                    return 0;
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                }
                return 0;
            }
        });

        //转换map
        Map<String,Object> result = new TreeMap<>();
        for(int i=0;i<reqList.size();i++){
            Object o = reqList.get(i);
            Class clazz = o.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for(Field field:fields){
                field.setAccessible(true);
                String sortStr1 = (String)field.get(o);
                if(sortStr1!=null && !"".equals(sortStr1)) {
                    result.put(headStr + "[" + i + "]." + field.getName(), sortStr1);
                }
            }
        }

        return result;

    }

    public static Map<String,Object> sortObject(Object o, String headStr) throws ClassNotFoundException,
            IllegalAccessException {
        Map<String,Object> result = new TreeMap<>();
        Class clazz = o.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for(Field field:fields){
            field.setAccessible(true);
            String sortStr1 = (String)field.get(o);
            if(sortStr1!=null && !"".equals(sortStr1)) {
                result.put(headStr + "." + field.getName(), sortStr1);
            }
        }

        return result;

    }

    //根据指定字段排序
    public static void sortList(List reqList, String sortFileld) {

        Collections.sort(reqList, new Comparator<Object>() {
            @Override
            public int compare(Object o1, Object o2) {
                Class oa1 = o1.getClass();
                Class oa2 = o2.getClass();
                try {
                    Field field1 = oa1.getDeclaredField(sortFileld);
                    Field field2 = oa2.getDeclaredField(sortFileld);
                    field1.setAccessible(true);
                    field2.setAccessible(true);
                    String sortStr1 = (String) field1.get(o1);
                    String sortStr2 = (String) field2.get(o2);
                    if (sortStr1.compareTo(sortStr2) > 0) {
                        return 1;
                    } else if (sortStr1.compareTo(sortStr2) < 0) {
                        return -1;
                    }
                    return 0;
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                }
                return 0;
            }
        });

    }

    /**
     * JSON 类型的字符串转换成 Map
     */
    public static void parseJSON2Map(Map jsonMap,String jsonStr,String parentKey){
        //字符串转换成JSON对象
        net.sf.json.JSONObject json = net.sf.json.JSONObject.fromObject(jsonStr);
        //最外层JSON解析
        for(Object k : json.keySet()){
            //JSONObject 实际上相当于一个Map集合，所以我们可以通过Key值获取Value
            Object v = json.get(k);
            //构造一个包含上层keyName的完整keyName
            String fullKey = (null == parentKey || parentKey.trim().equals("") ? k.toString() : parentKey + "." + k);

            if(v instanceof JSONArray){
                //如果内层还是数组的话，继续解析
                Iterator it = ((JSONArray) v).iterator();
                int num = 0;
                while(it.hasNext()){
                    Object o = it.next();
                    if(o instanceof net.sf.json.JSONObject){
                        net.sf.json.JSONObject json2 = (net.sf.json.JSONObject)o;
                        parseJSON2Map(jsonMap,json2.toString(),fullKey + "[" + num + "]");
                    }else{
                        jsonMap.put(fullKey + "[" + num + "]", o);
                    }
                    num++;

                }
            } else if(v.toString().contains("{")){
                parseJSON2Map(jsonMap,v.toString(),fullKey);
            }
            else{
                jsonMap.put(fullKey, v);
            }
        }
    }


    /**
     * 单层json转多层json，只能3层结构
     *  将带A[0].B,A[0].C,A[1].B,A[1].C转换成（A[0],{B,C}）,(A[1],{B,C})
     */
    public static Map<String,Object> parseJson2Json1(Map<String,Object> pa,Map<String,Object> map){
        Map<String,Object> maps = new HashMap<>();
        Map<String,Object> a1 = new HashMap<>();
        for (Entry<String, Object> entry : pa.entrySet()) {
            String  entryKey = entry.getKey();
            String[] keys = entryKey.split("\\.");
            if(keys.length == 1){
                map.put(entryKey,entry.getValue());
            }else if(keys[0].indexOf("[")> 0){

                parseMapObject(maps,entryKey,entry.getValue());

            }else{

                parseMapObject(maps,entryKey,entry.getValue());

            }

        }
        return maps;
    }

    public static void parseMapSimple(Map<String,Object> map,String key,Object value){

        if(key.indexOf("[")> 0){
            String entryKey1 = key.substring(0,key.indexOf("]")+1);
            String entryKey2 = key.substring(key.indexOf("]")+2);
            //先数组
            if(entryKey2.indexOf("[")> 0 ){
                Map<String,Object> reqMap =new HashMap<>();
                parseMapSimple(reqMap,entryKey2,value);

                if(map.get(entryKey1) !=null){
                    Map<String,Object> a2m = (Map<String,Object>)map.get(entryKey1);
                    compareMap(a2m,reqMap);
                }else{

                    map.put(entryKey1,reqMap);
                }


            }else{
                if(map.get(entryKey1) !=null){
                    Map<String,Object> a2m = (Map<String,Object>)map.get(entryKey1);
                    a2m.put(entryKey2,value);
                }else{
                    Map<String,Object> a2m = new HashMap<>();
                    a2m.put(entryKey2,value);
                    map.put(entryKey1,a2m);
                }


            }


        }else{
            map.put(key,value);

        }
    }

    public static void parseMapObject(Map<String,Object> map,String key,Object value){

        int dotIndex = key.indexOf(".");
        int khIndex =  key.indexOf("[");
        if(dotIndex> 0 || khIndex> 0){
            String entryKey1 = "";
            String entryKey2 = "";

            if(khIndex<0 || (dotIndex> 0 && key.indexOf(".")< key.indexOf("["))){
                entryKey1 = key.substring(0,key.indexOf("."));
                entryKey2 = key.substring(key.indexOf(".")+1);

            }else if(dotIndex<0 || (key.indexOf("[")> 0 && key.indexOf("[")<key.indexOf("."))){
                entryKey1 = key.substring(0,key.indexOf("]")+1);
                entryKey2 = key.substring(key.indexOf("]")+2);
            }

            if(entryKey2.indexOf("[")> 0 ||  entryKey2.indexOf(".")> 0){
                Map<String,Object> reqMap =new HashMap<>();
                parseMapObject(reqMap,entryKey2,value);

                if(map.get(entryKey1) !=null){
                    Map<String,Object> a2m = (Map<String,Object>)map.get(entryKey1);
                    boolean flag = compareMap(a2m,reqMap);
                    if(!flag) {
                        a2m.putAll(reqMap);
                    }
                }else{

                    map.put(entryKey1,reqMap);
                }


            }else{
                if(map.get(entryKey1) !=null){
                    Map<String,Object> a2m = (Map<String,Object>)map.get(entryKey1);
                    a2m.put(entryKey2,value);
                }else{
                    Map<String,Object> a2m = new HashMap<>();
                    a2m.put(entryKey2,value);
                    map.put(entryKey1,a2m);
                }


            }

        }else{
            map.put(key,value);
        }

    }

    public static boolean compareMap(Map<String,Object> a2,Map<String,Object> reqMap){

        boolean havesame = false;
        for (Entry<String, Object> entry : reqMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            for (Entry<String, Object> entry1 : a2.entrySet()) {
                if(entry1.getKey().equals(key)){
                    Object value2 = entry1.getValue();
                    if(value2 instanceof Map && value instanceof Map){
                        ((Map) value2).putAll((Map)value);
                        havesame = true;
                    }else{
                        //未知情况，无法覆盖
                    }
                    break;
                }
                if(entry1.getValue() instanceof Map){
                    return compareMap((Map<String,Object>)entry1.getValue(),reqMap);
                }
            }


        }
        return havesame;

    }

    /**
     * 将单层map结构转换成多层map结构（A）
     * @param a2
     * @param maps
     */
    public static void coventMap(Map<String,Object> a2,Map<String,Object> maps){

        for (Entry<String, Object> entry : a2.entrySet()) {
            String  entryKey = entry.getKey();
            String entryKeyTotal = entryKey;
            if(entryKey.indexOf("[")>0){
                entryKeyTotal = entryKey.substring(0,entryKey.indexOf("["));
            }else{
                if(entry.getValue() instanceof  Map){
                    maps.put(entryKey,entry.getValue());
                    continue;
                }
            }

            if(entry.getValue().toString().indexOf("[")>0){
                Map<String,Object> reqMap =new HashMap<>();
                Map<String,Object> reqMap1 = (Map)entry.getValue();  //fileLists[0]={fileUrl=34, fileId=111111}, mobile=3, custName=3, idNumber=3
                List<Map<String,Object>> lists = null;
                Map<String,Object> maps1 = new HashMap<>();
                if(maps.get(entryKeyTotal)!=null){
                    lists = (List<Map<String,Object>>)maps.get(entryKeyTotal);
                }else{
                    lists = new ArrayList<>();
                }
                for (Entry<String, Object> entry1 : reqMap1.entrySet()) {
                    String key1 = entry1.getKey();
                    Map<String,Object> temp = new HashMap<>();
                    temp.put(entry1.getKey(),entry1.getValue());
                    if(key1.indexOf("[")>0){
                        coventMap(temp,reqMap);
                        maps1.putAll(reqMap);
                    }else if(key1.indexOf(".")>0){
                        coventMapdot(temp,reqMap);
                        maps1.putAll(reqMap);
                    }else{
                        maps1.putAll(temp);
                    }
                }
                lists.add(maps1);
                maps.put(entryKeyTotal,lists);
                continue;
            }

            if(maps.get(entryKeyTotal)!=null){
                List<Map<String,Object>> lists = (List<Map<String,Object>>)maps.get(entryKeyTotal);
                lists.add((Map<String,Object>)entry.getValue());

            }else{

                List<Map<String,Object>> lists = new ArrayList<>();
                lists.add((Map<String,Object>)entry.getValue());
                maps.put(entryKeyTotal,lists);

            }

        }

    }


    public static void coventMapdot(Map<String,Object> a2,Map<String,Object> maps){


        for (Entry<String, Object> entry : a2.entrySet()) {
            String  entryKey = entry.getKey();
            String entryKeyTotal = entryKey.substring(0,entryKey.indexOf("."));

            if(entry.getValue() instanceof Map){

                continue;
            }else if(entry.getValue() instanceof String || entry.getValue() instanceof Integer ){
                Map<String,Object> temp = new HashMap<>();

                if(maps.get(entryKeyTotal)!=null){
                    Map<String,Object> maps1 = (Map<String,Object>)maps.get(entryKeyTotal);



                }else{

                    Map<String,Object> maps1 = new HashMap<>();


                }

            }



        }

    }


}
